#include "swpassociationgraphicitem.h"

#include "../../documents/data/graphicdata.h"
#include "../../undo/basicitemcommands.h"
#include "../../utils/undomanager.h"
#include "../../utils/validatormanager.h"
#include "graphicitemcommon.h"

#include <lineeditdelegate.h>

#include <QtGui/QGraphicsScene>

using namespace core;
using namespace gui;
using namespace swp;

typedef QPair<Property, AbstractLineGraphicItem::LabelAnchor> _Property;

SwpAssociationGraphicItem::SwpAssociationGraphicItem(QGraphicsItem* parent) :
    AbstractLineGraphicItem(
        QPointF(),
        QPointF(),
        QList<QPointF>(),
        parent),
        m_firstRoleName(),
        m_firstRoleMul(),
        m_secondRoleName(),
        m_secondRoleMul(),
        m_name(),
        m_propertyOrder(),
        m_properties(),
        m_multiplicityDelegate(0)
{
    init();
}

SwpAssociationGraphicItem::SwpAssociationGraphicItem(const QPointF& startPoint,
    const QPointF& endPoint,
    const QList<QPointF>& anchors,
    QGraphicsItem* parent) : AbstractLineGraphicItem(
        startPoint,
        endPoint,
        anchors,
        parent),
        m_firstRoleName(),
        m_firstRoleMul(),
        m_secondRoleName(),
        m_secondRoleMul(),
        m_name(),
        m_propertyOrder(),
        m_properties(),
        m_multiplicityDelegate(0)
{
    init();
}

SwpAssociationGraphicItem::~SwpAssociationGraphicItem()
{
    delete m_multiplicityDelegate;
}

int SwpAssociationGraphicItem::type() const
{
    return SWP_ASSOCIATION_ITEM;
}

QString SwpAssociationGraphicItem::name() const
{
    return QObject::tr("Association");
}

IEditorItem* SwpAssociationGraphicItem::copy() const
{
    return new SwpAssociationGraphicItem();
}

QList<Property> SwpAssociationGraphicItem::properties() const
{
    QList<Property> ret;

    foreach (const QString& name,
        m_propertyOrder)
    {
        ret.append(m_properties[name].first);
    }

    return ret;
}

QVariant SwpAssociationGraphicItem::propertyValue(
    const QString& propertyName) const
{
    QVariant ret;

    if (m_properties.contains(propertyName))
    {
        const _Property prop = m_properties[propertyName];
        ret = prop.first.value();
    }

    return ret;
}

void SwpAssociationGraphicItem::propertyChanged(const QString& property,
    const QVariant& newValue, bool silent)
{
    if (m_properties.contains(property) &&
        propertyValue(property) != newValue)
    {
        _Property prop = m_properties[property];

        if (!silent)
        {
            PropertyChangeCommand* command = new PropertyChangeCommand(
                this, prop.first, newValue);

            UndoManager::getInstance()->push(
                dynamic_cast<IDocumentData*>(scene()), command);
        }
        else
        {
            prop.first.setValue(newValue);
            setLabel(prop.second, newValue.toString());

            m_properties[property] = prop;
        }

        if (silent && isSelected()) {
            setSelected(false);
            setSelected(true);
        }

        if (silent)
        {
            GraphicData* data = dynamic_cast<GraphicData*>(m_documentData);

            Q_ASSERT(data != 0); // shouldn't be null

            data->emitDataChanged();
        }
    }
}

QVariantList SwpAssociationGraphicItem::optionList(
    const QString& propertyName) const
{
    QVariantList ret;

    return ret;
}

QVariantList SwpAssociationGraphicItem::autocomplete(
    const QString& propertyName) const
{
    QVariantList ret;

    return ret;
}

void SwpAssociationGraphicItem::init()
{
    m_multiplicityDelegate = new LineEditDelegate();
    m_multiplicityDelegate->setValidator(
        ValidatorManager::getInstance()->getValidator(
            "MultiplicityValidator"));

    m_firstRoleName.Name = "firstRoleName";
    m_firstRoleName.Text = QObject::tr("First role name");
    m_firstRoleName.setValue("");

    m_properties[m_firstRoleName.Name] = QPair<Property, LabelAnchor>(
        m_firstRoleName, AbstractLineGraphicItem::StartBelow);

    m_firstRoleMul.Name = "firstRoleMul";
    m_firstRoleMul.Text = QObject::tr("First role multiplicity");
    m_firstRoleMul.setValue("");
    m_firstRoleMul.setDelegate(m_multiplicityDelegate);

    m_properties[m_firstRoleMul.Name] = QPair<Property, LabelAnchor>(
        m_firstRoleMul, AbstractLineGraphicItem::StartAbove);

    m_secondRoleName.Name = "secondRoleName";
    m_secondRoleName.Text = QObject::tr("Second role name");
    m_secondRoleName.setValue("");
    m_secondRoleMul.setDelegate(m_multiplicityDelegate);

    m_properties[m_secondRoleName.Name] = QPair<Property, LabelAnchor>(
        m_secondRoleName, AbstractLineGraphicItem::EndBelow);

    m_secondRoleMul.Name = "secondRoleMul";
    m_secondRoleMul.Text = QObject::tr("Second role multiplicity");
    m_secondRoleMul.setValue("");

    m_properties[m_secondRoleMul.Name] = QPair<Property, LabelAnchor>(
        m_secondRoleMul, AbstractLineGraphicItem::EndAbove);

    m_name.Name = "name";
    m_name.Text = QObject::tr("Name");
    m_name.setValue("Uses");

    m_properties[m_name.Name] = QPair<Property, LabelAnchor>(
        m_name, AbstractLineGraphicItem::MiddleAbove);

    m_propertyOrder.append(m_name.Name);
    m_propertyOrder.append(m_firstRoleMul.Name);
    m_propertyOrder.append(m_secondRoleMul.Name);
    m_propertyOrder.append(m_firstRoleName.Name);
    m_propertyOrder.append(m_secondRoleName.Name);

    setLabel(AbstractLineGraphicItem::MiddleAbove,
        m_name.value().toString());

    setFlags(flags() | QGraphicsItem::ItemIsSelectable);
}
